import { ElMessage as ElMessage2, ElMessageBox } from "element-plus";
import {ElNotification} from 'element-plus'
import dayjs from 'dayjs'

import {ref, unref} from 'vue'

import { post } from "/src/api/index";

export const authPath = window.auth_type
export const tokenName = 'sessionid'
export const userInfoStorageName = 'user_info'

let propLabelMap = {
  workspace_name: '工作区',
  root_path: '路径',
  group_name: '组名称',
  name: '名称',
  extra_info: '扩展属性',
  remark: '备注',
  project_name: '项目名',
  project: '工程',
  package_name: '包名',
  file_type: '文件类型',
  file_template: '模板',
  no_overwrite: '是否覆盖',
  table_name: '表名',
  project_names: '项目列表',
  parameter_catalog_type: '方法名',
  parameter_catalog: '类型',
  sort_no: '排序',
  java_type: 'Java类型',
  remarks: '备注',
  parameter_is_like: '是否为LIKE',
  parameter_sql_value: 'SQL中的查找内容',
  parameter_without_test: '是否不生成test指令',
  parameter_sql: 'SQL语句',
  parameter_nullable: '是否允许为空',
  parameter_sql_value_ignore: '是否不在SQL中查找',
  java_imports: 'Java引入包',
  java_return_type: 'Java返回类型',
  is_interface: '是否为接口',
  parameter_is_import_excel: '是否为导入Excel接口',
  parameter_is_export_excel: '是否为导出Excel接口',
  is_disable: '是否有效',
  parameter_mode: '参数模式',
  update_time: '更新时间',
  content: '内容',
  value: '值',
  db_host: '服务器地址',
  db_port: '服务器端口',
  db_database: '数据库名',
  db_jdbcurl: 'JDBC串',
  db_classname: 'JDBC类',
}

export function parseTokenParams(file_template, token, key) {
  let _result = []
  if(file_template && token) {
    let _ss = file_template.split('{' + token + '&')
    if(_ss.length > 1) {
      for(let _s1 in _ss) {
        if(_s1 == 0) {
          continue
        }
        _s1 = _ss[_s1]
        let _lines = _s1.split('}')[0].split('&')
        for(let _s2 in _lines) {
          _s2 = _lines[_s2]
          let _pos = _s2.indexOf('=')
          if(_pos > 0) {
            let _l = _s2.substring(0, _pos).trim()
            let _r = _s2.substring(_pos+1, 200)
            if(_l && key == _l) {
              if(!_result.find(e => e == _r)) {
                _result.push(_r)
              }
            }
          }
        }
      }
    }
  }
  return _result
}

export function sortObject(obj) {
  let o = {}
  let a = []
  for(let p in obj) {
    a.push(p)
  }
  a = a.sort(function compareFunction(p1, p2) {return p1.localeCompare(p2, 'zh') })
  for(let p in a) {
    p = a[p]
    o[p] = obj[p]
  }
  return o
}
export function funcSortColumns (lColumns, rColumns, type) {
  rColumns.forEach( (item, index) => {
    if(propLabelMap[item.prop]) {
      item.label = propLabelMap[item.prop]
    }
    if (rColumns.filter(ele => ele.prop == item.prop).length > 1) {
      if (item.prop) {
        ElMessage.error('字段合并异常，'+type+',附加字段重复:'+item.prop)
      }
    }
  })
  lColumns.forEach( (item, index) => {
    if(item.prop == item.label && propLabelMap[item.prop]) {
      item.label = propLabelMap[item.prop]
    }
    if (lColumns.filter(ele => ele.prop == item.prop).length > 1) {
      if (item.prop) {
        ElMessage.error('字段合并异常，'+type+'基础字段重复:'+item.prop)
      }
    }
  })
  rColumns.forEach( (item, index) => {
    let lItem = lColumns.find( ele => ele.prop == item.prop && item.prop)
    if (lItem) {
      try {
        for(let p in lItem) {
          if (p in item) {
            try {
              for(let p2 in lItem[p]) {
                if (p2 in item[p]) {
  
                } else {
                  item[p][p2] = lItem[p][p2]
                }
              }
            }catch(ex) {
  
            }
          } else {
            item[p] = lItem[p]
          }
        }
      }catch(ex) {

      }

      try {
        for(let p in item) {
          if (p in lItem) {
            try {
              for(let p2 in item[p]) {
                lItem[p][p2] = item[p][p2]
              }
            }catch(ex) {
  
            }
          } else {
            lItem[p] = item[p]
          }
        }
      }catch(ex) {

      }
    }
    item.sortNo = index
  })
  lColumns.forEach( (item,index) => {
    item.sortNo = index
  })
  let columns = []
  let l = 0
  let r = 0
  let side = 'l'
  let c = 0
  while(l < lColumns.length || r < rColumns.length) {
    if (c++ > 2000) {
      console.error('lColumns', l, lColumns)
      console.error('rColumns', r, rColumns)
      ElMessage.error('无法处理columns');
      break;
    }
    if (side == 'l') {
      if (l >= lColumns.length) {
        if (r >= rColumns.length) {
          break;
        }
        side = 'r';
        continue;
      }
      let lItem = lColumns[l]
      let mItem;
      try {
        mItem = columns.find( ele => ele.prop == lItem.prop && ele.prop)
      }catch(ex) {
        console.error('columns非法:', columns)
        console.error('lItem', lItem)
        ElMessage.error('无法处理columns');
        console.error('ex', ex)
        break;
      }
      if (mItem) {
        l++
        if (l >= lColumns.length) {
          side = 'r'
        }
        continue;
      }
      let rItem = null
      if (r < rColumns.length) {
        rItem = rColumns.find( ele => ele.prop == lItem.prop && ele.prop)
      }
      if (rItem) {
        side = 'r'
      } else {
        columns.push(lItem)
        l++
        if (l >= lColumns.length) {
          side = 'r'
        }
      }
    } else if (side == 'r') {
      if (r >= rColumns.length) {
        if (l >= lColumns.length) {
          break;
        }
        side = 'l'
        continue;
      }
      let rItem = rColumns[r]
      if (!rItem.prop) {
        r++;
        side = 'l'
        continue;
      }
      columns.push(rItem)
      r++;
      if (r >= rColumns.length) {
        side = 'l'
        continue;
      }
      let lItem = lColumns.find( ele => ele.prop == rItem.prop && ele.prop)
      if (lItem) {
        //如果当前右侧元素出现在左侧，则继续处理右侧元素
        continue;
      }

      if (r < rColumns.length - 1) {
        //如果后续元素未出现在左侧，则继续处理右侧元素
        rItem = rColumns[r+1]
        lItem = lColumns.find( ele => ele.prop == rItem.prop && ele.prop)
        if (!lItem) {
          continue;
        }
      }
      side = 'l'
    }
  }
  return columns
}

export function copyEditColumns(self, self2) {
  self.editColumns.value.forEach( item => {
    if (item.prop == '#') {
      return;
    }
    if (self.custom.editColumns.find(ele => ele.prop == item.prop)) {
      return;
    }
    self.custom.editColumns.push(item)
    item.disabled = true
  })
  if (self2) {
    self.custom.columns = funcSortColumns(self2.custom.columns, self.custom.columns)
    self.custom.editColumns = funcSortColumns(self2.custom.editColumns, self.custom.editColumns)
    self.custom.queryColumns = funcSortColumns(self2.custom.queryColumns, self.custom.queryColumns)
    self.custom.remoteConfig = {...self2.custom.remoteConfig, ...self.custom.remoteConfig}
  }
}

export function getStorageValue(key) {
  if (key == tokenName) {
    return key
  }
  let item = localStorage.getItem(key)
  if (item) {
    try {
      let newItem = JSON.parse(item)
      try {
        newItem = JSON.parse(newItem)
      }catch(ex) {
      }
      return newItem;
    }catch(ex) {
      // console.error('getStorageValue fail', ex, key)
    }
  }
  return item;
}

export function setStorageValue(key, value) {
  return localStorage.setItem(key, JSON.stringify(value))
}

export function removeStorageValue(key) {
  return localStorage.removeItem(key)
}

export function arrayBufferToString(arr){
  if(typeof arr === 'string') {  
      return arr;  
  }  
  var dataview=new DataView(arr);
  var ints=new Uint8Array(arr.byteLength);
  for(var i=0;i<ints.length;i++){
    ints[i]=dataview.getUint8(i);
  }
  arr=ints;
  var str = '',  
      _arr = arr;  
  for(var i = 0; i < _arr.length; i++) {  
      var one = _arr[i].toString(2),  
          v = one.match(/^1+?(?=0)/);  
      if(v && one.length == 8) {  
          var bytesLength = v[0].length;  
          var store = _arr[i].toString(2).slice(7 - bytesLength);  
          for(var st = 1; st < bytesLength; st++) {  
              store += _arr[st + i].toString(2).slice(2);  
          }  
          str += String.fromCharCode(parseInt(store, 2));  
          i += bytesLength - 1;  
      } else {  
          str += String.fromCharCode(_arr[i]);  
      }  
  }  
  return str; 
}

export const ElMessage = {
  error: (msg, err) => {
    console.error(dayjs().format('YYYY-MM-DD HH:mm:ss'), msg)
    console.error('err', err)
    ElMessage2.error(msg)
  },
  success: (msg) => {
    console.warn(dayjs().format('YYYY-MM-DD HH:mm:ss'), msg)
    ElMessage2.success(msg)
  },
  warning: (msg) => {
    console.warn(dayjs().format('YYYY-MM-DD HH:mm:ss'), msg)
    ElMessage2.warning(msg)
  },

}

export function printLog() {
  return getStorageValue('print_log') == 1
}

export function saveAs() {
  let view = window
  if (
    typeof view === 'undefined' ||
    (typeof navigator !== 'undefined' &&
      /MSIE [1-9]\./.test(navigator.userAgent))
  ) {
    return
  }
  var doc = view.document,
    // only get URL when necessary in case Blob.js hasn't overridden it yet
    get_URL = function () {
      return view.URL || view.webkitURL || view
    },
    save_link = doc.createElementNS('http://www.w3.org/1999/xhtml', 'a'),
    can_use_save_link = 'download' in save_link,
    click = function (node) {
      var event = new MouseEvent('click')
      node.dispatchEvent(event)
    },
    is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
    is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
    throw_outside = function (ex) {
      ;(view.setImmediate || view.setTimeout)(function () {
        throw ex
      }, 0)
    },
    force_saveable_type = 'application/octet-stream',
    // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
    arbitrary_revoke_timeout = 1000 * 40, // in ms
    revoke = function (file) {
      var revoker = function () {
        if (typeof file === 'string') {
          // file is an object URL
          get_URL().revokeObjectURL(file)
        } else {
          // file is a File
          file.remove()
        }
      }
      setTimeout(revoker, arbitrary_revoke_timeout)
    },
    dispatch = function (filesaver, event_types, event) {
      event_types = [].concat(event_types)
      var i = event_types.length
      while (i--) {
        var listener = filesaver['on' + event_types[i]]
        if (typeof listener === 'function') {
          try {
            listener.call(filesaver, event || filesaver)
          } catch (ex) {
            throw_outside(ex)
          }
        }
      }
    },
    auto_bom = function (blob) {
      // prepend BOM for UTF-8 XML and text/* types (including HTML)
      // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
      if (
        /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(
          blob.type
        )
      ) {
        return new Blob([String.fromCharCode(0xfeff), blob], {
          type: blob.type,
        })
      }
      return blob
    },
    FileSaver = function (blob, name, no_auto_bom) {
      if (!no_auto_bom) {
        blob = auto_bom(blob)
      }
      // First try a.download, then web filesystem, then object URLs
      var filesaver = this,
        type = blob.type,
        force = type === force_saveable_type,
        object_url,
        dispatch_all = function () {
          dispatch(filesaver, 'writestart progress write writeend'.split(' '))
        },
        // on any filesys errors revert to saving with object URLs
        fs_error = function () {
          if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
            // Safari doesn't allow downloading of blob urls
            var reader = new FileReader()
            reader.onloadend = function () {
              var url = is_chrome_ios
                ? reader.result
                : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;')
              var popup = view.open(url, '_blank')
              if (!popup) view.location.href = url
              url = undefined // release reference before dispatching
              filesaver.readyState = filesaver.DONE
              dispatch_all()
            }
            reader.readAsDataURL(blob)
            filesaver.readyState = filesaver.INIT
            return
          }
          // don't create more object URLs than needed
          if (!object_url) {
            object_url = get_URL().createObjectURL(blob)
          }
          if (force) {
            view.location.href = object_url
          } else {
            var opened = view.open(object_url, '_blank')
            if (!opened) {
              // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
              view.location.href = object_url
            }
          }
          filesaver.readyState = filesaver.DONE
          dispatch_all()
          revoke(object_url)
        }
      filesaver.readyState = filesaver.INIT

      if (can_use_save_link) {
        object_url = get_URL().createObjectURL(blob)
        setTimeout(function () {
          save_link.href = object_url
          save_link.download = name
          click(save_link)
          dispatch_all()
          revoke(object_url)
          filesaver.readyState = filesaver.DONE
        })
        return
      }

      fs_error()
    },
    FS_proto = FileSaver.prototype,
    saveAs = function (blob, name, no_auto_bom) {
      return new FileSaver(blob, name || blob.name || 'download', no_auto_bom)
    }
  // IE 10+ (native saveAs)
  if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
    return function (blob, name, no_auto_bom) {
      name = name || blob.name || 'download'

      if (!no_auto_bom) {
        blob = auto_bom(blob)
      }
      return navigator.msSaveOrOpenBlob(blob, name)
    }
  }

  FS_proto.abort = function () {}
  FS_proto.readyState = FS_proto.INIT = 0
  FS_proto.WRITING = 1
  FS_proto.DONE = 2

  FS_proto.error =
    FS_proto.onwritestart =
    FS_proto.onprogress =
    FS_proto.onwrite =
    FS_proto.onabort =
    FS_proto.onerror =
    FS_proto.onwriteend =
      null

  return saveAs
}


export function exportWorkspace(param) {
  let { workspace_name : workspaceName, with_id} = param
  let datas = {}
  let ignoreSqlTableSet = {}
  let tableSet = {}

  return post('sdp_workspace', 'list', {
    name: workspaceName
  })
    .then((data) => {
      datas['sdp_workspace'] = data.map((item) => ({
        ...item,
        id: with_id ? item.id : null,
        name: null,
        db_username: null,
        db_password: null,
      }))
      return post('sdp_workspace_config', 'list', {
        workspace_name: workspaceName,
        query_options: {
          order_by: param.sdp_workspace_config.custom.columns.filter(ele => ele.order).map(ele => {
            let obj = {}
            obj[ele.prop] = ele.order
            return obj
          })
        },
      })
        .then((data) => {
          datas['sdp_workspace_config'] = data.map((item) => ({
            ...item,
            id: with_id ? item.id : null,
            workspace_name: null,
          }))
          return post('sdp_project', 'list', {
            workspace_name: workspaceName,
            query_options: {
              order_by: param.sdp_project.custom.columns.filter(ele => ele.order).map(ele => {
                let obj = {}
                obj[ele.prop] = ele.order
                return obj
              })
            },
          })
        })
        .then((data) => {
          datas['sdp_project'] = data.map((item) => ({
            ...item,
            id: with_id ? item.id : null,
            workspace_name: null,
          })).map( ele => {
            if(ele.tables) {
              let tables = ele.tables.split(',')
              
              tables.map(e => {
                let n = e
                let a = e
                if(e.indexOf(' as ') > 0) {
                  n = e.split(' as ')[0].trim();
                  a = e.split(' as ')[1].trim();
                }
                if(e.indexOf('-') > 0) {
                  n = n.split('-')[0]
                  a = a.split('-')[0]
                  if(!with_id) {
                    ignoreSqlTableSet[a] = 1
                  }
                }
                tableSet[a] = n
              })
              console.log('exportWorkspace ignoreSqlTableSet,with_id', with_id, ignoreSqlTableSet)
              console.log('exportWorkspace tableSet:',with_id, tableSet)
              ele.tables = tables.filter(e => with_id || e.indexOf('-') < 0).join(',')
            }
            return ele
          })
          let root_path_common_last = ''
          let root_path_common = ''
          let root_path_common_char_index = 0
          for ( let root_path_common_char_index = 0; root_path_common_char_index < 200; root_path_common_char_index++) {
            let root_path_common_last_char = undefined
            let isDiff = false
            let isLast = false
            for(let project in datas['sdp_project']) {
              let root_path = datas['sdp_project'][project].root_path
              if (!root_path || root_path.indexOf('(root)') == 0) {
                isDiff = true;
                continue;
              }
              if (root_path_common_char_index >= root_path.length) {
                isDiff = true;
                break;
              }
              if (root_path_common_char_index == root_path.length - 1) {
                isLast = true;
              }
              let current_char = root_path.substring(root_path_common_char_index, root_path_common_char_index + 1);
              if (root_path_common_last_char === undefined) {
                root_path_common_last_char = current_char
              } else {
                if (root_path_common_last_char != current_char) {
                  isDiff = true;
                  break;
                }
              }
            }
            if (isDiff) {
              break;
            } else {
              if(root_path_common_last_char) {
                root_path_common += root_path_common_last_char
                if (root_path_common_last_char == '/' || root_path_common_last_char == '\\' || isLast) {
                  root_path_common_last = root_path_common
                }
              }
            }
          }
          if (root_path_common_last && !with_id) {
            let last_char = root_path_common_last.substring(root_path_common_last.length - 1)
            let more_char = ''
            if (last_char == '/' || last_char == '\\') {
              more_char = last_char
            }
            datas['sdp_project'] = datas['sdp_project'].map( item => {
              let root_path = item.root_path
              if (root_path && root_path.indexOf(root_path_common_last) == 0) {
                item.root_path = '(root)' + more_char + root_path.substring(root_path_common_last.length)
              }
              return item;
            })
          }
          return post('sdp_template', 'list', {
            workspace_name: workspaceName,
            query_options: {
              order_by: param.sdp_template.custom.columns.filter(ele => ele.order).map(ele => {
                let obj = {}
                obj[ele.prop] = ele.order
                return obj
              })
            },
          })
        })
        .then((data) => {
          datas['sdp_template'] = data.map((item) => {
            item = {
              ...item,
              id: with_id ? item.id : null,
              workspace_name: null,
            }
            let itemNames = ['file_template', 'remark']
            itemNames.forEach((itemName) => {
              let lines = item[itemName]
              let destLines = []
              if (lines) {
                lines = lines.split('\n')
                for (let line in lines) {
                  line = lines[line]
                  destLines.push(line)
                }
                item[itemName] = destLines
              }
            })
            itemNames = ['extra_info']
            itemNames.forEach((itemName) => {
              if (item[itemName]) {
                try {
                  item[itemName] = JSON.parse(item[itemName])
                } catch (ex) {
                  console.error('ex', ex)
                  console.error('extra_info非法', item)
                  throw new Error(ex+','+itemName+'非JSON：'+item[itemName]+',详细记录：'+JSON.stringify(item))                  
                }
              }
            })
            return item
          })
          return post('sdp_sql', 'list', {
            workspace_name: workspaceName,
            query_options: {
              order_by: param.sdp_sql.custom.columns.filter(ele => ele.order).map(ele => {
                let obj = {}
                obj[ele.prop] = ele.order
                return obj
              })
            },
          })
        })
        .then((data) => {
          console.log('ignoreSqlTableSet', ignoreSqlTableSet)
          // datas['sdp_sql'] = data.filter(item => with_id ||( !ignoreSqlTableSet[item.table_name] && tableSet[item.table_name])).map((item) => {
          datas['sdp_sql'] = data.map((item) => {
            item = {
              ...item,
              id: with_id ? item.id : null,
              workspace_name: null,
            }
            let itemNames = ['parameter_sql', 'java_imports', 'remarks']
            itemNames.forEach((itemName) => {
              let lines = item[itemName]
              let destLines = []
              if (lines) {
                lines = lines.split('\n')
                for (let line in lines) {
                  line = lines[line]
                  destLines.push(line)
                }
                item[itemName] = destLines
              }
            })
            itemNames = ['extra_info']
            itemNames.forEach((itemName) => {
              if (item[itemName]) {
                try {
                  item[itemName] = JSON.parse(item[itemName])
                } catch (ex) {
                  console.error('ex', ex)
                  console.error('extra_info非法', item)
                  throw new Error(ex+','+itemName+'非JSON：'+item[itemName]+',详细记录：'+JSON.stringify(item))                  
                }
              }
            })
            return item
          })
        })
        .then((data) => {
          return datas
        })
    })
}

export function getSelection() {
  var txt = ''
  if (window.getSelection) {
    txt = window.getSelection()
  } else if (document.getSelection) {
    txt = document.getSelection()
  } else if (document.selection) {
    txt = document.selection.createRange().text
  } else return ''
  return txt + ''
}


export function batchUpdateValue(param) {
  let { self, selectOnly } = param
  param = param.param
  let module = unref(self.module)
  if (selectOnly) {
    let selectRows = unref(self.selectRows)
    if (!selectRows || !selectRows.length) {
      ElMessage.error('请选择记录后再操作')
      return
    }
  }
  let txt = getSelection()
  let { button } = param
  if (!txt) {
    let dialogInfo = unref(self.batchUpdateValueDialogInfo)
    if (selectOnly) {
      dialogInfo.title = '批量替换值(选中条目)'
    } else {
      dialogInfo.title = '批量替换值(全部结果)'
    }
    dialogInfo.show({...param, dialogInfo})
    // ElMessage.error(`请选择文字后再操作`);
    return;
  }
  if (!self.last_click_cell) {
    ElMessage.error(`请选择后再操作`);
    return;
  }
  let column = unref(self.columns).find(ele => ele.prop == self.last_click_cell.property)
  if (!self.last_click_cell || !self.last_click_cell.property || !column) {
    ElMessage.error(`逻辑错误94`);
    return;
  }
  if (column.prop == 'workspace_name') {
    ElMessage.error(`不可以批量修改属性：工作区`);
    return;
  }
  ElMessageBox.prompt('请输入新值。原值：'+txt+'，属性：'+column.label+'（'+self.last_click_cell.property+'）', '批量替换值', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    closeOnPressEscape:false,
    closeOnClickModal:false,
    inputValidator: (val) => {
      if (val === null||val.length < 1) {
        return false;
      }
    },
    inputErrorMessage: '此项不能为空',
  })
    .then(({ value }) => {
      if (!value) {
        return;
      }
      button.loading = true;
      self.handleSearch({
        pageNo:1,
        pageSize: 10000,
        withoutSetData: true,
      }).then( data => {
        if (selectOnly) {
          data = unref(self.selectRows)
        }
        let foundItem = data.filter(ele => ele[column.prop] && ele[column.prop].indexOf(txt) >= 0)
        if (foundItem && foundItem.length) {
          let count = 0
          foundItem.forEach( ele => {
            let form = {id:ele.id}
            form[column.prop] = ele[column.prop].replace(txt, value)

            post(module, 'update', form)
            .then((data) => {
              count++
              if (count == foundItem.length) {
                button.loading = false
                ElMessage.success('更新成功')
                self.handleSearch()
              }
            })
            .catch((err) => {
              button.loading = false
              ElMessage.error(`无法更新，错误：${ex}`);
            })
          })
        }
      })
    })
}

export function getDuration(param) {
  let now = new Date();
  let diff = parseInt((now.getTime() - param.getTime())/1000)
  if (diff > 60) {
    diff = parseInt(diff / 60) + '分' + (diff % 60) + '秒'
  } else {
    diff += '秒'
  }
  return diff
}

export function fireExecute(param) {
  let { self } = param
  let { isAi } = param
  param = param.param
  let module = unref(self.module)
  let { button } = param
  let { query, selectRows } = self
  query = unref(query)
  selectRows = unref(selectRows)

  if (!query.workspace_name && !(selectRows && selectRows.length)) {
    ElMessage.error(`必须选择一个条目或设置查询条件；工作区`);
    return;
  }
  let workspace_name = query.workspace_name
  if (!workspace_name) {
    workspace_name = selectRows[0].workspace_name
  }
  post('sdp_project', 'list', {workspace_name})
  .then( data => {
    let missRoot = false;
    data.forEach(item => {
      if (item.root_path.indexOf('(root)') >= 0) {
        missRoot = true;
      }
    })
    if (missRoot) {
      ElMessage.error('必须先设置sdp_project的(root)路径')
      return;
    }
    ElMessageBox.confirm('是否要生成工作区的所有文件：'+workspace_name, '生成文件', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    })
      .then(() => {
        button.loading = true;
        let form = {workspace_name}
        let offset = 100
  
        let notification = ElNotification.warning({
          title: '生成文件',
          message: workspace_name+' 开始生成文件（'+dayjs().format('HH:mm:ss')+'）...',
          offset,
          duration: 0,
        })
        let now = new Date();
        let obj = {name:JSON.stringify(form)}
        if(isAi) {
          obj.is_ai = 1
          if(selectRows?.length) {
            obj.param_info = JSON.stringify({
              selected:selectRows.map(e => {
                return {
                  ...e,
                  file_template:null,
                  extra_info:null,
                  remark:null,
                  name_diff:null,
                  id:null,
                }
              })
            })
            
          }
        }
        post('sdp_project', 'execute', obj)
        .then((data) => {
          console.log('fireExecute 914', data)
          button.loading = false
          try {
            notification.close();
          }catch(ex) {
          }
          ElNotification.success({
            title: '生成文件',
            message: workspace_name+' 生成成功。耗时：'+getDuration(now),
            offset,
            duration: 0,
          })
        })
        .catch((err) => {
          button.loading = false
          try {
            notification.close();
          }catch(ex) {
          }
          ElNotification.error({
            title: '生成文件',
            message: workspace_name+' 生成失败。耗时：'+getDuration(now),
            offset,
            duration: 0,
          })
        })
      })
  
  })
}

export function getQuery() {
  let querys = window.location.href.split('?')
  let query = {}
  if (querys.length > 1) {
    querys = querys[1].split('&')
    querys.forEach( ele => {
      ele = ele.split('=')
      let name = ele[0]
      let value
      if (ele.length > 1) {
        value = ele[1]
      }
      query[name] = value
    })
  }
  return query
}

let sdp_language_key_common = [
  /*
  {
    prop: '==以下为通用属性',
    label: '==',
  },
  {
    prop: 'has_blobs',
    label: '包含BLOBS字段',
  },
  {
    prop: 'column_is_last',
    label: '是最后一个字段',
  },
  {
    prop: 'column_is_first',
    label: '是第一个字段',
  },
  */
]
let sdp_language_common = [
  {
    prop: 'global_prepare',
    label: '全局预处理',
  },
  {
    prop: 'only_first_lower',
    label: '仅首字母小写',
  },
  {
    prop: 'empty_as_lower_camel_column_name',
    label: '为空时等价于小驼峰字段名',
  },
  {
    prop: 'empty_as_upper_camel_column_name',
    label: '为空时等价于大驼峰字段名',
  },
  {
    prop: 'empty_as_lower_snake_column_name',
    label: '为空时等价于小写下划线命名规则字段名',
  },
  {
    prop: 'empty_as_upper_snake_column_name',
    label: '为空时等价于大写下划线命名规则字段名',
  },
  {
    prop: 'empty_as_lower_camel_table_name',
    label: '为空时等价于小驼峰表名',
  },
  {
    prop: 'empty_as_lower_camel_alias_table_name',
    label: '为空时等价于小驼峰表别名',
  },
  {
    prop: 'empty_as_upper_camel_table_name',
    label: '为空时等价于大驼峰表名',
  },
  {
    prop: 'empty_as_upper_camel_alias_table_name',
    label: '为空时等价于大驼峰表别名',
  },
  {
    prop: 'empty_as_lower_snake_table_name',
    label: '为空时等价于小写下划线命名规则表名',
  },
  {
    prop: 'empty_as_lower_snake_alias_table_name',
    label: '为空时等价于小写下划线命名规则表别名',
  },
  {
    prop: 'empty_as_upper_snake_table_name',
    label: '为空时等价于大写下划线命名规则表名',
  },
  {
    prop: 'empty_as_upper_snake_alias_table_name',
    label: '为空时等价于大写下划线命名规则表别名',
  },
  {
    prop: 'case',
    label: '命名规则',
  },
  {
    prop: 'is_nullable',
    label: '是否允许为空',
  },
  {
    prop: 'is_replace_by_value',
    label: '用value属性替换，未定义时等于空串',
  },
  {
    prop: 'result_contains',
    label: '字段注释是否包含字符串',
  },
  {
    prop: 'is_primary_key',
    label: '字段是否为主键',
  },
]

let sdp_language_key_base = [
  {
    prop: 'is_ajax',
    label: '小写加下划线分割',
  },
  {
    prop: 'is_dash',
    label: '小写加破折号分割',
  },
  {
    prop: 'is_lower',
    label: '转换为小写',
  },
  {
    prop: 'is_upper',
    label: '转换为大写',
  },
  {
    prop: 'is_first_lower',
    label: '驼峰（首字母小写）',
  },
  {
    prop: 'is_java_name',
    label: 'Java标识符（保留字时自动转换为非保留字）',
  },
  {
    prop: 'is_dup_prefix',
    label: '换行前复制前缀',
  },
  {
    prop: 'with_delimited',
    label: 'SQL保留字两端加入`符号',
  },
  {
    prop: 'has_java_return_type',
    label: '是否设置了Java返回类型',
  },
]
export const sdp_language_block_common = [
  {
    prop: 'has_blobs',
    label: '预处理-包含BLOB字段时继续处理其他过滤条件，否则返回空集',
  },
  {
    prop: 'has_primary_key',
    label: '预处理-定义了主键时继续处理其他过滤条件，否则返回空集',
  },
  {
    prop: 'has_auto_increment',
    label: '预处理-定义了自增字段时继续处理其他过滤条件，否则返回空集',
  },
  {
    prop: 'only_primary_key',
    label: '过滤-仅包含主键',
  },
  {
    prop: 'is_only_param_columns',
    label: '过滤-仅包含自定义参数；父元素必须为sqls或sql',
  },
  {
    prop: 'is_only_response_columns',
    label: '过滤-仅包含结果字段',
  },
  {
    prop: 'is_both_request_columns',
    label: '过滤-仅包含同时为数据库字段和自定义参数',
  },
  {
    prop: 'is_both_response_columns',
    label: '过滤-仅包含同时为数据库字段和自定义结果字段',
  },
  {
    prop: 'is_only_request_columns',
    label: '过滤=仅包含请求字段',
  },
  {
    prop: 'is_only_miss_extra_request_columns',
    label: '过滤=仅包含扩展请求字段',
  },
  {
    prop: 'is_only_miss_extra_response_columns',
    label: '过滤=仅包含扩展结果字段',
  },
  {
    prop: 'is_no_extra_request_columns',
    label: '过滤=不包含扩展请求字段',
  },
  {
    prop: 'is_no_extra_response_columns',
    label: '过滤=不包含扩展结果字段',
  },
  {
    prop: 'extra_request_columns',
    label: '包含自定义基础方法请求参数',
    sample: 'extra_request_columns=add',
  },
  {
    prop: 'extra_response_columns',
    label: '包含自定义基础方法结果参数',
    sample: 'extra_response_columns=query'
  },
  {
    prop: 'empty_as_table',
    label: '无结果时返回一行',
  },
  {
    prop: 'has_dup',
    label: '存在重复字段名时返回第一个字段',
  },
  {
    prop: 'not_empty_as_empty',
    label: '存在结果时清空结果',
  },
  {
    prop: 'content_id',
    label: '将内容记录到全局标记中',
  },
  {
    prop: 'is_empty_content',
    label: '全局标记的内容为空时满足条件',
  },
  {
    prop: 'is_not_empty_content',
    label: '全局标记的内容不为空时满足条件',
  },
  {
    prop: 'include_param_columns',
    label: '包含参数字段',
  },
  {
    prop: 'is_fix_dup',
    label: '是否去除重复字段(缺省为1)'
  },
  {
    prop: 'include_all_sql_param',
    label: '包含所有sql及字段',
  },
  {
    prop: 'include_response_columns',
    label: '包含结果字段',
  },
  {
    prop: 'column_is_first',
    label: '仅返回第一个条目',
  },
  {
    prop: 'column_is_last',
    label: '仅返回最后一个条目',
  },
  {
    prop: 'has_columns_1',
    label: '过滤-包含任意一个字段（返回第一个找到的字段）',
    sample: 'has_columns_1=name, age',
  },
  {
    prop: 'has_columns_0',
    label: '过滤-不包含任何字段（找到时返回空集合，未找到时返回集合第一个条目）',
  },
  {
    prop: 'discard',
    label: '过滤-忽略字段',
  },
  {
    prop: 'has_columns',
    label: '过滤-通过名称过滤字段',
  },
  {
    prop: 'column_name',
    label: '过滤-字段名相同时',
  },
  {
    prop: 'is_string',
    label: '字段类型是否为字符串',
  },
  {
    prop: 'is_integer',
    label: '字段类型是否为整数',
  },
  {
    prop: 'is_long',
    label: '字段类型是否为长整数',
  },
  {
    prop: 'is_big_decimal',
    label: '字段类型是否为BigDecimal',
  },
  {
    prop: 'is_date',
    label: '字段类型是否为日期',
  },
  {
    prop: 'is_blob',
    label: '字段类型是否为BLOB',
  },
  {
    prop: 'is_primary_key',
    label: '字段是否为主键',
  },
  {
    prop: 'is_primary_key_multiple',
    label: '包含主键，且主键字段数大于1',
  },
  {
    prop: 'is_auto_increment',
    label: '字段为自增',
  },
  {
    prop: 'is_simple',
    label: 'SQL是否为简单SQL',
  },
  {
    prop: 'is_interface',
    label: 'SQL是否为接口',
  },
  {
    prop: 'is_import_excel',
    label: '自定义方法为导入Excel自定义方法',
  },
  {
    prop: 'param_is_nullable',
    label: '自定义字段允许为空',
  },
  {
    prop: 'param_is_like',
    label: '自定义字段为LIKE类型',
  },
  {
    prop: 'has_column_java_imports',
    label: '是否包含imports声明',
  },
  {
    prop: 'has_java_return_type',
    label: '是否定义了Java返回类型',
  },
  {
    prop: 'has_java_field_type_with_package',
    label: '字段类型是否包含包名',
  },
  {
    prop: 'is_dup',
    label: '是否允许包含重复字段',
  },
  {
    prop: '==以下为扩展属性中定义的属性',
    label: '=='
  },
  {
    prop: 'is_update',
    label: '是否为DML语句',
  },
  {
    prop: 'is_frontend_list',
    label: '是否为前端列表页接口',
  },
  {
    prop: 'is_collection',
    label: '是否为集合参数，例如in操作符',
  },
  {
    prop: 'is_dollar',
    label: '是否为$参数(会引起SQL注入)',
  },
  {
    prop: 'is_nolist',
    label: '是否不返回数组接口',
  },
  {
    prop: 'is_formdata',
    label: '是否为FormData格式',
  },
  {
    prop: 'has_is_update',
    label: '是否包含DML语句',
  },
  {
    prop: 'has_is_frontend_list',
    label: '是否包含前端列表页接口',
  },
  {
    prop: 'has_is_nolist',
    label: '是否包含不返回数组接口',
  },
  {
    prop: 'has_is_formdata',
    label: '是否包含FormData类型接口',
  },
]
export const sdp_language_template_extra_info = [
  {
    prop: '==以下为扩展属性定义的内容',
    label: '==',
  },
  {
    prop: 'is_ai',
    label: '扩展属性-是否为ai',
  },
]
export const sdp_language_project_extra_info = [
  {
    prop: '==以下为扩展属性定义的内容',
    label: '==',
  },
  {
    prop: 'ai_tables',
    label: '扩展属性-ai表',
    type: 'textarea',
  },
]
export const sdp_language_workspace_extra_info = [
  {
    prop: '==以下为扩展属性定义的内容',
    label: '==',
  },
  {
    prop: 'is_local_ollama',
    label: '扩展属性-是否为本地ollama',
  },
  {
    prop: 'model',
    label: '模型名称',
    type: 'select',
  },
]

export const sdp_language_sql_extra_info = [
  {
    prop: '==以下为扩展属性定义的内容',
    label: '==',
  },
  {
    prop: 'is_collection',
    label: '扩展属性-是否为集合参数，例如in操作符',
  },
  {
    prop: 'is_dollar',
    label: '是否为$参数(会引起SQL注入)',
  },
  {
    prop: 'is_nolist',
    label: '扩展属性-是否不返回列表类型',
  },
  {
    prop: 'is_formdata',
    label: '扩展属性-是否为FormData接口',
  },
  {
    prop: 'is_frontend_list',
    label: '扩展属性-是否为前端列表页',
  },
  {
    prop: 'is_update',
    label: '扩展属性-是否为DML语句',
  },
  {
    prop: 'sql_replace_line',
    type: 'textarea',
    label: '扩展属性-替换sql xml中的内容(整行)',
  },
  {
    prop: 'url',
    label: '扩展属性',
  },
  {
    prop: 'response_default_value',
    label: '扩展属性',
  },
  {
    prop: 'request_json_name',
    label: '扩展属性',
  },
  {
    prop: 'request_extra_param',
    label: '扩展属性',
    suggestion: '请求扩展参数，例如：Integer p1,(注意依据模板写法，开始或结尾需要有一个逗号)',
  },
  {
    prop: 'request_extra_param_simple',
    label: '扩展属性',
    suggestion: '简单模式请求扩展参数，例如：p1,',
  },
  {
    prop: 'request_extra_param_web',
    label: '扩展属性',
    suggestion: 'Web接口的请求扩展参数，例如：@RequestParam Integer p1,',
  },
  {
    prop: 'response_json_name',
    label: '扩展属性',
  },
]

export const sdp_language = {
  keys: [
    {
      prop: 'alias_table_name',
      label: '表别名，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
        {
          prop: 'is_prefix_as_url_ending',
          label: '前缀转换为url前缀加斜线',
        },
        {
          prop: 'is_prefix_as_rename',
          label: '前缀转换为别名',
        }
      ]
    },
    {
      prop: 'table_name',
      label: '表名，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
      ]
    },
    {
      prop: 'table_comment',
      label: '表注释',
      props: [
        ...sdp_language_common,
        {
          prop: 'is_first_line',
          label: '仅首行',
        },
        {
          prop: 'is_dup_prefix',
          label: '换行前复制前缀',
        },
      ]
    },
    {
      prop: 'sql_name',
      label: 'SQL方法名称，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
      ]
    },
    {
      prop: 'sql_param_name',
      label: 'SQL方法参数名，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
      ]
    },
    {
      prop: 'config',
      label: '工作区参数',
      suggestion: 'config&name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '名称',
        },
        {
          prop: 'ignore_prefix_as_package_ending',
          label: '忽略前缀处理',
        },
      ]
    },
    {
      prop: 'global_prepare',
      label: '全局预处理占位',
      suggestion: 'global_prepare&name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '名称',
        }
      ]
    },
    {
      prop: 'auto_import_annotation',
      label: '自动引入java包',
    },
    {
      prop: 'project_root_path_tail',
      label: '项目路径的结尾部分',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '项目名称',
        },
        {
          prop: 'split',
          label: '分隔串',
        }
      ]
    },
    {
      prop: 'replace_by_sql',
      label: '替换信息',
      suggestion: 'replace_by_sql&name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '名称',
        },
      ]
    },
    {
      prop: 'template',
      label: '模板',
      suggestion: 'template&project_name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'project_name',
          label: '项目',
        },
        {
          prop: 'name',
          label: '名称',
        },
      ]
    },
    {
      prop: 'project_extra_info',
      label: '项目扩展属性',
      suggestion: 'project_extra_info&name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '名称',
        },
      ]
    },
    {
      prop: 'project_extra_info_table',
      label: '表扩展属性',
      suggestion: 'project_extra_info_table&name=',
      props: [
        ...sdp_language_common,
        {
          prop: 'name',
          label: '名称',
        },
      ]
    },
    {
      prop: 'value',
      label: '常量',
      suggestion: 'value&value=',
      props: [
        ...sdp_language_common,
        {
          prop: 'value',
          label: '值',
        }
      ]
    },
    {
      prop: 'file_name',
      label: '文件名',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'file_date',
      label: '文件时间（注释头',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'package_name',
      label: '包名',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
      ]
    },
    {
      prop: 'serialVersionUID',
      label: '序列化唯一编号',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_name',
      label: '字段名，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
        {
          prop: 'is_rename',
          label: '用扩展属性重命名，未定义时等价于无此参数',
        },
        {
          prop: 'is_replace',
          label: '用扩展属性替换，未定义时等于空串',
        },
        {
          prop: 'is_replace_by_sql',
          label: '用SQL信息中的属性替换，未定义时等于空串',
        },
      ]
    },
    {
      prop: 'column_method_name',
      label: '字段-方法名，首字母大写驼峰',
      props: [
        ...sdp_language_common,
        ...sdp_language_key_base,
        {
          prop: 'is_rename',
          label: '重命名，未定义时等价于无此参数',
        },
        {
          prop: 'is_replace',
          label: '替换为，未定义时等于空串',
        },
      ]
    },
    {
      prop: 'column_sql',
      label: '字段-SQL语句',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_simple_sql_with_star',
      label: '字段-简单SQL语句-暴露*号',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_simple_sql',
      label: '字段-简单SQL语句',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_ori_sql',
      label: '字段-原始SQL语句',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_index',
      label: '字段序号',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_comment',
      label: '字段-注释',
      props: [
        ...sdp_language_common,
        {
          prop: 'is_first_line',
          label: '仅保留首行',
        },
        {
          prop: 'is_dup_prefix',
          label: '换行前复制前缀',
        },
      ]
    },
    {
      prop: 'column_jsonformat_for_date',
      label: '字段-jsonformat-日期',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_format_for_date',
      label: '字段-format-日期',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_length',
      label: '字段-长度',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_jsonfield_for_date',
      label: '字段-jsonfield-日期',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_java_return_type',
      label: '字段-Java返回类型',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_java_imports',
      label: '字段-Java imports',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_java_type',
      label: '字段-Java类型',
      props: [
        ...sdp_language_common,
        {
          prop: 'is_full_name',
          label: '全名',
        },
      ]
    },
    {
      prop: 'column_sql_type',
      label: '字段-Sql类型',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_import_java',
      label: '导入java包',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_name_for_repository',
      label: '字段-名称（用于repository）',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_name_dash_for_repository',
      label: '字段-名称-下划线分隔（用于repository）',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_parameter_type_for_mapper',
      label: '字段-参数类型（用于mapper）',
      props: [
        ...sdp_language_common,
      ]
    },
    {
      prop: 'column_param_for_repository',
      label: '字段-参数（用于repository）',
      props: [
        ...sdp_language_common,
      ]
    },
  ].map(ele => ({ ...ele, props: [...(ele.props || []), ...sdp_language_key_common]})),
  blocks: [
    {
      prop: 'columns',
      label: '全部字段',
      props: [
        ...sdp_language_block_common,
        {
          prop: 'is_replace_by_sql',
          label: '是否使用SQL替换字段',
        }
      ]
    },
    {
      prop: 'column',
      label: '字段；允许子集合',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'primary_key',
      label: '主键',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'unique_keys',
      label: '唯一性索引',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'unique_key_fields',
      label: '唯一性索引（For Fields）；允许子集合（仅限父元素为unique_keys）',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'table',
      label: '表',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'tables',
      label: '全部表',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'sql',
      label: 'SQL或自定义方法',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'sqls',
      label: '全部SQL或自定义方法；允许子集合',
      props: [
        ...sdp_language_block_common,
      ]
    },
    {
      prop: 'methods',
      label: '全部自定义方法',
      props: [
        ...sdp_language_block_common,
      ]
    },
  ]
}